const {ccclass, property} = cc._decorator;
import EnumDir from '../struct/EnumDir';
import YangInfo from '../struct/YangInfo';
import PrefabManager from '../xf/manager/PrefabManager';
import pfutil from '../xf/util/pfutil';
import ViewBase from '../xf/ViewBase';
import MdTip from './MdTip';
import LData from './../manager/LData';
import MdWin from './MdWin';
import MdFail from './MdFail';
import MdPause from './MdPause';
import AndroidTool from './AndroidTool';
import ToolUtil from './ToolUtil';
import SoundManager from '../manager/SoundManager';


@ccclass
export default class MdGame extends ViewBase {

    private static _inst:MdGame;

    public static get inst()
    {
        if(this._inst==null)
        {
            let v=cc.instantiate(PrefabManager.getPrefab("GameView"));

            this._inst=v.getComponent(MdGame);
        }

        return this._inst;
    }


    @property(cc.Node)
    container:cc.Node=null;

    @property(cc.Node)
    show:cc.Node=null;

    @property(cc.Node)
    zz:cc.Node=null;  //遮罩

    @property(cc.Node)
    btns:cc.Node=null;  //按钮组

    @property(cc.Node)
    chooose:cc.Node=null;  //选择视图

    @property(cc.Label)
    jsq:cc.Label=null;  //计时器

    @property(cc.Label)
    level:cc.Label=null;  //关卡

    
   // public grids:Map<number,GridInfo>=new Map();

   public grids_nums:Array<number>=[]

   public grids:Map<number,number>=new Map();

   public yangs:Array<YangInfo>=[];

   public h_c=20;
   public l_c=20;
   public ww=50;

   public oper:Array<YangInfo>=[];

   public game_flag=false;
   public pause_flag=false;
   private mTimer=null

   protected onLoad(): void {
        var self=this
        let helper = {
            reset : function(){
                self.pause_flag=false;
                self.realCheHui()
            },
            tips : function(){
                self.pause_flag=false;
                self.realGaoLiang()
            },
            addTime : function(){
                self.realAddTime()
                self.pause_flag=false;
            },
            flip:function(){
                self.pause_flag=false;
                self.realFanZhuan()
            }
        }
        window["game"]=helper;
   }

    protected onDestroy(): void {
        MdGame._inst=null;
        clearInterval(this.mTimer);
    }

   start () 
   {
    this.mTimer=setInterval(()=>{
        console.log("timetime")
        this.onTimer();
      },1000);
   }


   public cleanData()
   {
        this.grids_nums=[];
        this.grids=new Map();

        this.yangs=[];


        this.container.removeAllChildren();

        this.zz.parent=this.container;
        this.chooose.active=false

   }



   public startGame()
   {

       this.pause_flag=false;

       this.cleanData();

       this.showView();

       this.randYang();
       this.updateView();

       this.scheduleOnce(()=>{
        this.checkShow();
       },0.1)

       if(ToolUtil.Instance.isZh()){
        this.level.string="第 "+LData.lv+" 关";
       }else{
        this.level.string="Level "+LData.lv;
       }
      
       this.setTimeNum();
   }

   private setLvData()
   {
      let lv=LData.lv;

      if(lv==1)
      {
        this.l_c=6;
        this.h_c=6;

        this.container.scale=1.5;

        this.time=60;
      }
      else if(lv==2)
      {
        this.l_c=25;
        this.h_c=25;

        this.container.scale=1;

        this.time=120;
      }
      else
      {
        this.l_c=25;
        this.h_c=25; 

        this.time=180;

        this.container.scale=0.8;
        
      }
   }


   private dirs:Array<number>=[1,2,3,4];

   public randYang()
   {
       this.setLvData();

       this.yangs=[];

       for(let i=0;i<this.l_c;i++)
       {
           for(let k=0;k<this.h_c;k++)
           {              
               this.grids_nums.push(i*10000+k);
               this.grids.set(i*10000+k,0);
           }
       }

       pfutil.randSort(this.grids_nums);

       let index=0;

       
       while(true)
       {
           if(this.grids_nums.length==0)
           {
               break;
           }

           pfutil.randSort(this.dirs);

           let flag=false;

           if(pfutil.random(0,100)<50)
           {
                for(let i=0;i<4;i++)
                {
                    let id=this.grids_nums[0];
    
                    let id2=this.getNextGrid(id,this.dirs[i]);
    
                    if(id2==-1)
                    {
                        continue;
                    }
    
                    if(this.grids.get(id2)==1)
                    {
                        continue;
                    }
    
                    let info=new YangInfo();
                    info.dir=this.dirs[i];
                    info.grids.push(id);
                    info.grids.push(id2);
    
                    this.grids.set(id,1);
                    this.grids.set(id2,1);
    
                    pfutil.removeVal(this.grids_nums,id);
                    pfutil.removeVal(this.grids_nums,id2);
    
                    this.yangs.push(info);
    
                    flag=true;
    
                    break;
                }
           }

           if(flag==false)
           {
              // console.warn("咋回事呀");
               this.grids_nums.shift();
           }

           index++;

           if(index>10000)
           {
               break;
           }
       }


       if(LData.lv ==1 &&  this.canAllOut()==false)
       {
           this.randYang();
       }

       if(this.yangs.length<4)
       {
          this.randYang();
       }

   }

   public getNextGrid(id:number,dir:number)
   {
         let i=Math.floor(id/10000);
         let k=id%10000;

         if(dir==EnumDir.up)
         {
            k--;
         }
         else if(dir==EnumDir.down)
         {
            k++;
         }
         else if(dir==EnumDir.left)
         {
            i--;
         }
         else if(dir==EnumDir.right)
         {
            i++;
         }

         let val=i*10000+k;

         if(this.grids.has(val)==true)
         {
             return val;
         }
         else
         {
             return -1;
         }
   }

   public updateView()
   {
         for(let i=0;i<this.yangs.length;i++)
         {
             let yang=this.getYang(this.yangs[i]);
             yang.parent=this.container;

             yang.on(cc.Node.EventType.TOUCH_END,this.onClick,this)

             this.yangs[i].yang=yang;
             yang.opacity=0;
         }
   }

   public getYang(info:YangInfo):cc.Node
   {

       let node:cc.Node ;

       if(info.yang==null)
       {
          node=  cc.instantiate(PrefabManager.getPrefab("Yang"));

         // console.warn("创建的羊---"+(<any>node)._id)
       }
       else
       {
          node=  info.yang;
       }
      

       let x=Math.floor(info.grids[0]/10000);
       let y=info.grids[0]%10000;

       x= (x * this.ww -  this.ww/2 * this.l_c )+this.ww/2;

       y= ( this.ww/2 * this.h_c - y * this.ww )-this.ww/2;

       if(info.dir==EnumDir.up)
       {
           y+=this.ww/2;
           node.angle=0

       }
       else if(info.dir==EnumDir.down)
       {
           y-=this.ww/2;

           node.angle=180
       }
       else if(info.dir==EnumDir.left)
       {
           x-=this.ww/2;

           node.angle=90
       }
       else if(info.dir==EnumDir.right)
       {
           x+=this.ww/2;

           node.angle=270
       }

      

       node.x=x;
       node.y=y;

       return node;

   }

   public onClick(event:cc.Event.EventTouch)
   {

        if(this.game_flag==false)
        {
            return;
        }

        this.zz.active=false;
        for(let i=0;i<this.yangs.length;i++)
        {
            this.yangs[i].yang.zIndex=0;
        }


     //   console.warn("被点击的羊---"+(<any>event.target)._id)

       for(let i=0;i<this.yangs.length;i++)
       {
        //   console.warn("被查询的羊---"+(<any>this.yangs[i].yang)._id)

           if(this.yangs[i].yang == event.target)
           {
             //  console.warn(this.yangs[i].grids[0]+"的羊被点击了");

               if(this.fz_flag==true)
               {
                   this.fanZhuan2(this.yangs[i]);
               }
               else
               {
                  this.moveYang(this.yangs[i]);
               }

               return;
           }
       }

       
   }

   //检测出来移动位置
   public moveYang(info:YangInfo)
   {

       for(let i=0;i<info.grids.length;i++)
       {
           this.grids.set(info.grids[i],0);
       }

       let i=Math.floor(info.grids[0]/10000);
       let k=info.grids[0]%10000;

       let add=0;

       if(info.dir==EnumDir.up)
       {
           k-=1;

           while(true)
           {
               add+=1;

               if(k-add<0)
               {
                   add=100;
                   break;
               }

               if(this.grids.get(i*10000+(k-add))==1)
               {
                   add-=1;
                   break;
               }
           }

           if(add!=0)
           {
              info.addLast();
              this.oper.push(info);
           }

           if(add==100)
           {
               //可以消失
               SoundManager.playSound("success")
                info.move = cc.tween(info.yang)
               .to(0.1,{y:info.yang.y+15})
               .to(2,{y:info.yang.y + 2000})
               .call(()=>{
                   console.warn("向上移出完成");
                   info.move=null;
               })
               .start();

               this.delYang(info);

           }
           else
           {
               //碰撞
               info.move= cc.tween(info.yang)
               .to(0.1,{y:info.yang.y+15})
               .to(0.2 * add,{y:info.yang.y+15 + this.ww * add })
               .delay(0.1)
               .to(0.1,{y:info.yang.y+15 + this.ww * add -15})
               .call(()=>{
                SoundManager.playSound("fail")
                   console.warn("向上移出完成");
                   info.move=null;
               })
               .start();


               for(let i=0;i<info.grids.length;i++)
               {
                  let a=Math.floor(info.grids[i]/10000);
                  let b=info.grids[i]%10000;

                  b=b-add;

                  info.grids[i]=a*10000 +b;

                  this.grids.set(info.grids[i],1);
               }


           }
       }
       else if(info.dir==EnumDir.down)
       {
           k+=1;

           while(true)
           {
               add+=1;

               if(k+add>=this.h_c)
               {
                   add=100;
                   break;
               }

               if(this.grids.get(i*10000+(k+add))==1)
               {
                   add-=1;
                   break;
               }
           }

           if(add!=0)
           {
              info.addLast();
              this.oper.push(info);
           }

           if(add==100)
           {
               
               //可以消失
               SoundManager.playSound("success")
               info.move = cc.tween(info.yang)
               .to(0.1,{y:info.yang.y-15})
               .to(2,{y:info.yang.y - 2000})
               .call(()=>{
                   console.warn("向上移出完成");
                   info.move=null;


               })
               .start();

               this.delYang(info);

           }
           else
           {
               //碰撞
              info.move =  cc.tween(info.yang)
               .to(0.1,{y:info.yang.y-15})
               .to(0.2 * add,{y:info.yang.y-15 - this.ww * add })
               .delay(0.1)
               .to(0.1,{y:info.yang.y-15 - this.ww * add +15})
               .call(()=>{
                SoundManager.playSound("fail")
                   console.warn("向下移出完成");
                   info.move=null;
               })
               .start();


               for(let i=0;i<info.grids.length;i++)
               {
                  let a=Math.floor(info.grids[i]/10000);
                  let b=info.grids[i]%10000;

                  b=b+add;

                  info.grids[i]=a*10000 +b;

                  this.grids.set(info.grids[i],1);
               }

           }
       }
       else   if(info.dir==EnumDir.left)
       {
           i-=1;

           while(true)
           {
               add+=1;

               if(i-add<0)
               {
                   add=100;
                   break;
               }

               if(this.grids.get((i-add)*10000+k)==1)
               {
                   add-=1;
                   break;
               }
           }

           if(add!=0)
           {
              info.addLast();
              this.oper.push(info);
           }

           if(add==100)
           {
               //可以消失
               SoundManager.playSound("success")
               info.move = cc.tween(info.yang)
               .to(0.1,{x:info.yang.x-15})
               .to(2,{x:info.yang.x - 2000})
               .call(()=>{
                   console.warn("向上移出完成");
                   info.move=null;
               })
               .start();

               this.delYang(info);
           }
           else
           {
               //碰撞
               info.move = cc.tween(info.yang)
               .to(0.1,{x:info.yang.x-15})
               .to(0.2 * add,{x:info.yang.x-15 - this.ww * add })
               .delay(0.1)
               .to(0.1,{x:info.yang.x-15 - this.ww * add +15})
               .call(()=>{
                SoundManager.playSound("fail")
                   console.warn("向上移出完成");
                   info.move=null;
               })
               .start();


               for(let i=0;i<info.grids.length;i++)
               {

                  let a=Math.floor(info.grids[i]/10000);
                  let b=info.grids[i]%10000;

                  a=a-add;

                  info.grids[i]=a*10000 +b;

                  this.grids.set(info.grids[i],1);
               }


           }
       }
       else if(info.dir==EnumDir.right)
       {
           i+=1;

           while(true)
           {
               add+=1;

               if(i+add>=this.l_c)
               {
                   add=100;
                   break;
               }

               if(this.grids.get((i+add)*10000+k)==1)
               {
                   add-=1;
                   break;
               }
           }

           if(add!=0)
           {
              info.addLast();
              this.oper.push(info);
           }

           if(add==100)
           {
               
               //可以消失
               SoundManager.playSound("success")
               info.move = cc.tween(info.yang)
               .to(0.1,{x:info.yang.x+15})
               .to(2,{x:info.yang.x + 2000})
               .call(()=>{
                   console.warn("向上移出完成");
                   info.move=null;

               })
               .start();

               this.delYang(info);

           }
           else
           {
               //碰撞
               info.move = cc.tween(info.yang)
               .to(0.1,{x:info.yang.x+15})
               .to(0.2 * add,{x:info.yang.x+15 + this.ww * add })
               .delay(0.1)
               .to(0.1,{x:info.yang.x+15 + this.ww * add -15})
               .call(()=>{
                SoundManager.playSound("fail")
                   console.warn("向下移出完成");
                   info.move=null;
               })
               .start();


               for(let i=0;i<info.grids.length;i++)
               {
                  let a=Math.floor(info.grids[i]/10000);
                  let b=info.grids[i]%10000;

                  a=a+add;

                  info.grids[i]=a*10000 +b;

                  this.grids.set(info.grids[i],1);
               }

           }
       }

   }

   public delYang(info:YangInfo)
   {
       for(let i=0;i<this.yangs.length;i++)
       {
           if(this.yangs[i]==info)
           {
               console.warn("删除的羊---"+(<any>this.yangs[i].yang)._id)

               this.yangs.splice(i,1);
           }
       }
   }

   //检测展示
   public checkShow()
   {
      let arr=[];

      let show_fw=this.node.convertToWorldSpaceAR(new cc.Vec2(0,0));

      let up=show_fw.y-this.show.height/2;
      let down=show_fw.y+this.show.height/2;
      let left=show_fw.x-this.show.width/2;
      let right=show_fw.x+this.show.width/2;

      for(let i=0;i<this.yangs.length;i++)
      {
        let yang=this.yangs[i];

        let curr_pos=yang.yang.parent.convertToWorldSpaceAR(yang.yang.position);

        if(curr_pos.x<left)
        {
            arr.push(yang);
            continue;
        }

        if(curr_pos.x>right)
        {
            arr.push(yang);
            continue;
        }

        if(curr_pos.y<up)
        {
            arr.push(yang);
            continue;
        }

        if(curr_pos.y>down)
        {
            arr.push(yang);
            continue;
        }
      }

      for(let i=0;i<arr.length;i++)
      {
        for(let k=0;k<this.yangs.length;k++)
        {
            if(this.yangs[k]==arr[i])
            {
                this.yangs[k].yang.parent=null;

                for(let a=0;a<this.yangs[k].grids.length;a++)
                {
                    this.grids.set(this.yangs[k].grids[a],0);
                }

             //   console.warn("不展示的羊---"+(<any>this.yangs[k].yang)._id)

                this.yangs.splice(k,1);

                break;
            }
        }
      }


      this.checkDir();

      for(let i=0;i<this.yangs.length;i++)
      {
         let yang=this.yangs[i];
         yang.yang.scale=0;
         yang.yang.opacity=255;

        let delay=pfutil.random(50,100)/1000

         cc.tween(yang.yang)
         .delay(delay)
         .to(0.5,{scale:1})
         .start();
      }

      this.game_flag=true;
   }
   

   //检测可以跑出去的羊
   public checkOut():Array<YangInfo>
   {
        let arr:Array<YangInfo>=[];

        for(let a=0;a<this.yangs.length;a++)
        {
            let info=this.yangs[a];
     
            let i=Math.floor(info.grids[0]/10000);
            let k=info.grids[0]%10000;

            if(this.grids.get(info.grids[0])==0)
            {
                continue;
            }
     
            let add=0;
     
            if(info.dir==EnumDir.up)
            {
                k-=1;
     
                while(true)
                {
                    add+=1;
     
                    if(k-add<0)
                    {
                        add=100;
                        break;
                    }
     
                    if(this.grids.get(i*10000+(k-add))==1)
                    {
                        add-=1;
                        break;
                    }
                }
     
                if(add==100)
                {
                    arr.push(info);
                }
               
            }
            else if(info.dir==EnumDir.down)
            {
                k+=1;
     
                while(true)
                {
                    add+=1;
     
                    if(k+add>=this.h_c)
                    {
                        add=100;
                        break;
                    }
     
                    if(this.grids.get(i*10000+(k+add))==1)
                    {
                        add-=1;
                        break;
                    }
                }
     
                if(add==100)
                {
                    arr.push(info);
                }
               
            }
            else   if(info.dir==EnumDir.left)
            {
                i-=1;
     
                while(true)
                {
                    add+=1;
     
                    if(i-add<0)
                    {
                        add=100;
                        break;
                    }
     
                    if(this.grids.get((i-add)*10000+k)==1)
                    {
                        add-=1;
                        break;
                    }
                }
     
                if(add==100)
                {
                    arr.push(info);
     
                }
               
            }
            else if(info.dir==EnumDir.right)
            {
                i+=1;
     
                while(true)
                {
                    add+=1;
     
                    if(i+add>=this.l_c)
                    {
                        add=100;
                        break;
                    }
     
                    if(this.grids.get((i+add)*10000+k)==1)
                    {
                        add-=1;
                        break;
                    }
                }
     
                if(add==100)
                {
                    arr.push(info);     
                }
            }
        }

        return arr;
   }

  
   public canAllOut()
   {

      let jilu:Array<number> =[];

      while(true)
      {
        let aa=this.checkOut();

        if(aa.length==0)
        {
            console.error("不可全部消除");
            break;
        }
  
        for(let i=0;i<aa.length;i++)
        {
           for(let k=0;k<aa[i].grids.length;k++)
           {
              jilu.push(aa[i].grids[k]);
              this.grids.set(aa[i].grids[k],0);
           }
        } 
  
        if(jilu.length==this.yangs.length*2)
        {
            console.error("可以全部消除")

            for(let i=0;i<jilu.length;i++)
            {
                this.grids.set(jilu[i],1);
            }

            return true;
        }
      }

      return false;

   }


   //撤回
   public cheHui()
   {
       if(this.oper.length==0)
       {
          if(ToolUtil.Instance.isZh()){
            MdTip.inst.showTip("没有可撤回的操作");
          }else{
            MdTip.inst.showTip("No undoable actions");
          }
          return;
       }

       if(cc.sys.platform==cc.sys.ANDROID){
            this.pause_flag=true;
            AndroidTool.Instance.loadVideoAd("ad_reset")
       }else{
            this.realCheHui()
       }
   }

   public realCheHui(){
        let info=this.oper.pop();

        if(info.move!=null)
        {
        info.move.stop(); 
        }

        for(let i=0;i<info.grids.length;i++)
        {
            this.grids.set(info.grids[i],0);
        }

        info.huiChe();

        for(let i=0;i<info.grids.length;i++)
        {
            this.grids.set(info.grids[i],1);
        }

        info.yang = this.getYang(info);

        if(this.yangs.indexOf(info)==-1)
        {
            this.yangs.push(info);
        }
   }

   //高亮
   public gaoLiang()
   {
        let arr=this.checkOut();

        if(arr.length==0)
        {
            if(ToolUtil.Instance.isZh()){
                MdTip.inst.showTip("没有可消除的动物");
            }else{
                MdTip.inst.showTip("No animals to remove");
            }
            
            return;
        }

        if(cc.sys.platform==cc.sys.ANDROID){
            this.pause_flag=true;
            AndroidTool.Instance.loadVideoAd("ad_tips")
       }else{
            this.realGaoLiang()
       }
   }

   public realGaoLiang(){
    let arr=this.checkOut();

    this.zz.active=true;

    this.zz.zIndex=99;

    for(let i=0;i<arr.length;i++)
    {
        arr[i].yang.zIndex=100;
    }
   }

   public fz_flag=false;
   public fanZhuan1()
   {
       if(this.yangs.length==0)
       {
           return ;
       }

       if(cc.sys.platform==cc.sys.ANDROID){
            this.pause_flag=true;
            AndroidTool.Instance.loadVideoAd("ad_flip")
        }else{
            this.realFanZhuan()
        }
   }

   public realFanZhuan(){
    this.btns.active=false;

    this.fz_flag=true;

    this.chooose.active=true;

     for(let i=0;i<this.yangs.length;i++)
     {
         this.yangs[i].yang.zIndex=100;
     }
   }

   public addTime()
   {
        if(cc.sys.platform==cc.sys.ANDROID){
            this.pause_flag=true;
            AndroidTool.Instance.loadVideoAd("ad_add_time")
        }else{
            this.realAddTime()
        }
      
   }

   public realAddTime(){
    this.time+=60;
    this.setTimeNum();
   }

   public fanZhuan2(info:YangInfo)
   {
       if(this.yangs.length==0)
       {
           return ;
       }

       this.btns.active=true;

       this.fz_flag=false;

       this.chooose.active=false;

       this.fanZhuan3(info);
   }

   public fanZhuan3(info:YangInfo)
   {
        info.dir = (info.dir-1+2)%4 +1;
        info.grids.reverse();

        info.yang=this.getYang(info);     
   }

   public time=240;

   private onTimer()
   {
       if(this.game_flag==false)
       {
         return;
       }

       if(this.pause_flag==true)
       {
         return ;
       }

       this.time--;

       if(this.time<0)
       {
          //游戏失败
          this.game_flag=false;

          MdFail.inst.showView();

          //弹窗
          return;
       }

       this.setTimeNum();
   }

   public setTimeNum()
   {
      let tt=Math.floor(this.time/60);

      let ss=this.time%60;

      this.jsq.string="0"+tt+":"+(ss<10?"0"+ss:ss);

   }

   private checkDir()
   {

      let map:Map<number,Array<YangInfo>>=new Map();

      let map2:Map<number,Array<YangInfo>>=new Map();

      for(let i=0;i<this.yangs.length;i++)
      {
          let info=this.yangs[i];

          if(info.dir==EnumDir.left ||info.dir==EnumDir.right )
          {
               let g=Math.floor(info.grids[0]%10000);

               if(info.dir==EnumDir.right)
               {
                   this.fanZhuan3(info);
               }

               if(map.has(g)==false)
               {
                  map.set(g,new Array());
               }

               map.get(g).push(info);
          }
          else
          {

                if(info.dir==EnumDir.down)
                {
                   this.fanZhuan3(info);
                }

                 let g=Math.floor(info.grids[0]/10000);

                 if(map2.has(g)==false)
                 {
                    map2.set(g,new Array());
                 }

                 map2.get(g).push(info);
            
          }
      }

      map.forEach((val:Array<YangInfo>,key)=>{

        val.sort((v1,v2)=>{
              
            let a1=Math.floor(v1.grids[0]/10000);
            let a2=Math.floor(v2.grids[0]/10000);

            return a1-a2;
        })

        let  index=pfutil.random(0,val.length+1);

        for(let i=index;i<val.length;i++)
        {
            this.fanZhuan3(val[i]);
        }


      });

      map2.forEach((val:Array<YangInfo>,key)=>{

        val.sort((v1,v2)=>{
              
            let a1=Math.floor(v1.grids[0]%10000);
            let a2=Math.floor(v2.grids[0]%10000);

            return a1-a2;
        })

        let  index=pfutil.random(0,val.length+1);

        for(let i=index;i<val.length;i++)
        {
            this.fanZhuan3(val[i]);
        }
     
      });
   }

   public update()
   {
          if(this.game_flag==true)
          {
             if(this.yangs.length==0)
             {
                this.game_flag=false;

                this.gameOver();
             }
          }
   }

   private gameOver()
   {
      LData.lv++;
      if(cc.sys.platform==cc.sys.ANDROID){
        AndroidTool.Instance.onLevel(LData.lv)
      }

      setTimeout(() => {

        MdWin.inst.showView();
        
      }, 1000);
   }

   public onPause()
   {
      this.pause_flag=true;
      MdPause.inst.showView();
   }


}